/*
 * IndexedDictionaryActivity.java
 *
 * Copyright(c) 2010
 * Michael Kroez
 * kroez@studiorutton.de
 *
 * All rights reserved.
 *
 * $Id$
 * 
 */

package de.studiorutton.gerengdic.indexeddictionary;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.LayoutAnimationController;
import android.view.animation.TranslateAnimation;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;

import de.studiorutton.colorschemes.Buttonizer;
import de.studiorutton.colorschemes.IColorSchemeMapper;
import de.studiorutton.gerengdic.AboutDialogs;
import de.studiorutton.gerengdic.Preferences;
import de.studiorutton.gerengdic.Prefs;
import de.studiorutton.gerengdic.R;
import de.studiorutton.gerengdic.Rotate3dAnimation;
import de.studiorutton.gerengdic.databaseaccess.ContentAccess;
import de.studiorutton.gerengdic.databaseaccess.DatabaseAccessException;
import de.studiorutton.gerengdic.databaseaccess.DatabaseAccess.ViewRecord;
import de.studiorutton.gerengdic.databaseaccess.LanguageAccess.IndexPositionAccess.IndexAll;
import de.studiorutton.gerengdic.dictionary.DictionaryActivity;
import de.studiorutton.gerengdic.history.DictionaryCommand;
import de.studiorutton.gerengdic.history.HistoryActivity;
import de.studiorutton.gerengdic.history.IndexedDictionaryCommand;
import de.studiorutton.gerengdic.indexeddictionary.IndexedDictionary;
import de.studiorutton.gerengdic.indexeddictionary.IIndexedDictionaryView;
import de.studiorutton.gerengdic.update.UpdateDatabaseListActivity;
import de.studiorutton.thresholdedittext.ThresholdEditText;
import de.studiorutton.thresholdedittext.ThresholdTextChanged;

public class IndexedDictionaryActivity extends ListActivity implements
		IIndexedDictionaryView {
	private final static String TAG = "learningwords";
	private ThresholdEditText et;
	private Button b;
	private Button eb;
	private ListView lv;
	private RelativeLayout rl;

	private final static int DISPLAY_AUTOCOMPLETE_LIST = 1;
	private final static int DISPLAY_RESULT_LIST = 2;
	private final static boolean EXECUTE_ANIMATION = false;

	private static final int SEARCH_FRESH = 1;
	private static final int SEARCH_NO = 2;
	private static final int SEARCH_REFRESH = 3;

	public static boolean RESTART_AUTOCOMPLETE;

	private static final String KEY_PACKAGE = "de.studiorutton.gerengdic.IndexDictionaryActivity.";
	private static final String KEY_WORD = "word";
	private static final String KEY_LANG = "lang";
	private static final String KEY_AUTOCOMPLETE = "autocomplete";

	private IndexedDictionary id;
	private AboutDialogs ad;
	private final static int DIALOG_TITLE_SELECT = 1;
	private boolean comesFromHistory = false;

	private Bundle savedBundle;
	private boolean executeSavedBundle;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		// Log.d(TAG, "IndexedDictionaryActivity:onCreate");
		setContentView(R.layout.indexeddictionary);
		getWindow().setFormat(PixelFormat.RGBA_8888);

		if (savedInstanceState != null && !savedInstanceState.isEmpty()) {
			savedBundle = savedInstanceState;
			executeSavedBundle = true;
		}

	}

	@Override
	protected void onStart() {
		super.onStart();
		// Log.d(TAG, "IndexedDictionaryActivity:onStart");

		id = IndexedDictionary.get();
		ad = new AboutDialogs(this);

		et = (ThresholdEditText) findViewById(R.id.indexedsearchtext);
		b = (Button) findViewById(R.id.indexedsearchlanguage);
		eb = (Button) findViewById(R.id.erasebutton);
		lv = getListView();

		setListAnimation();
		IColorSchemeMapper csmi = Prefs.getInstance().getColorSchemeMapper();

		LinearLayout ll = (LinearLayout) findViewById(R.id.indexeddictionary);
		ll.setBackgroundColor(csmi.getBackgroundColor());
		rl = (RelativeLayout) findViewById(R.id.searchparent);
		rl.setBackgroundDrawable(csmi.getTitleStyle().getSearchBackground());
		lv.setDivider(csmi.getListDividerDrawable());

		boolean eraseButtonInvisible = !Prefs.getInstance()
				.getEraseButtonEnabled();
		eb.setBackgroundDrawable(csmi.getTitleStyle().getButtons()
				.getDrawable(Buttonizer.ERASE_DRAWABLE));
		checkClearVisibility(eraseButtonInvisible);
	}

	@Override
	protected void onResume() {
		super.onResume();
		// Log.d(TAG, "IndexedDictionaryActivity:onResume");

		try {
			// if (isLaunching())
			id.init();
		} catch (Exception e) {
			showErrorDialog(e.getLocalizedMessage());
		}

		id.setIndexedDictionaryListener(this);

		int executeSearch = executeExtras();

		updateEditText();
		updateLanguageButton();
		updateSearchList(true);
		updateClearButton();

		if (executeSearch != SEARCH_NO)
			executeCommand(executeSearch);

		if (RESTART_AUTOCOMPLETE)
			startAutocompleteSearch(null);

		// final RelativeLayout rl = this.rl;
		// ViewTreeObserver vto = rl.getViewTreeObserver();
		// vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
		// public void onGlobalLayout() {
		// Log.d( TAG, "IndexedDictionary: searchparent height (in pixels): " +
		// rl.getWidth() + "x" + rl.getHeight());
		// }
		// });
		//
		// final EditText et = this.et;
		// ViewTreeObserver eto = et.getViewTreeObserver();
		// eto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
		// public void onGlobalLayout() {
		// Log.d( TAG, "IndexedDictionary: searchtext size (in pixels): " +
		// et.getWidth() + "x" + et.getHeight());
		// }
		// });

	}

	@Override
	protected void onPause() {
		super.onPause();
		// Log.d(TAG, "IndexedDictionaryActivity:onPause");
		saveListPosition();

		if (isFinishing()) {
			Log.d(TAG, "* IndexedDictionary cleared.");
			IndexedDictionary.release();
			id = null;
		}
	}

	@Override
	protected void onStop() {
		super.onPause();
		// Log.d(TAG, "IndexedDictionaryActivity:onStop");

	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		// Log.d(TAG, "IndexedDictionaryActivity:onDestroy");
	}

	@Override
	public void onRestart() {
		super.onRestart();
		Log.d(TAG, "IndexedDictionaryActivity:onRestart");

	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);

		outState.putString(IndexedDictionaryCommand.MY_SEARCH_STRING_KEY,
				id.getSearchString());
		outState.putInt(IndexedDictionaryCommand.MY_SEARCH_LANG_KEY,
				id.getLanguage());
		outState.putBoolean(
				IndexedDictionaryCommand.MY_SEARCH_AUTOCOMPLETE_KEY,
				id.isAutoComplete());

	}

	@Override
	public Dialog onCreateDialog(int id) {
		switch (id) {
		case DIALOG_TITLE_SELECT:
			return dialogTitleSelect();
		default:
			return ad.onCreateDialog(id);
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.indexeddictionarymenu, menu);
		return true;
	}

	protected int executeExtras() {
		Bundle extras;
		if (executeSavedBundle) {
			extras = savedBundle;
		} else
			extras = getIntent().getExtras();

		if (extras != null) {
			String searchString = extras
					.getString(IndexedDictionaryCommand.MY_SEARCH_STRING_KEY);
			id.setSearchString(searchString);

			int searchLang = extras
					.getInt(IndexedDictionaryCommand.MY_SEARCH_LANG_KEY);
			id.setLanguage(searchLang);

			if (extras
					.containsKey(IndexedDictionaryCommand.MY_SEARCH_AUTOCOMPLETE_KEY))
				id.setIsAutoComplete(extras
						.getBoolean(IndexedDictionaryCommand.MY_SEARCH_AUTOCOMPLETE_KEY));
			else
				id.setIsAutoComplete(false);

			comesFromHistory = true;

			if (id.equalsLastSearchString(searchString))
				return SEARCH_REFRESH;
			else
				return SEARCH_FRESH;

		}
		return SEARCH_NO;
	}

	protected void executeCommand(int executeSearch) {
		if (executeSearch == SEARCH_FRESH) {
			IndexAll ia = null;
			try {
				ia = id.retrieveIndexAll(id.getSearchString(), id.getLanguage());
			} catch (DatabaseAccessException e) {
				showErrorDialog(e.getLocalizedMessage());
			}
			if (ia == null)
				return;

			id.createIndexList(ia);
		}
		updateEditText();
		updateLanguageButton();
		updateSearchList(true);
	}

	private void setListAnimation() {
		AnimationSet set = new AnimationSet(true);

		Animation animation = new AlphaAnimation(0.0f, 1.0f);
		animation.setDuration(50);
		set.addAnimation(animation);

		animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f,
				Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF,
				-1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
		animation.setDuration(100);
		set.addAnimation(animation);

		LayoutAnimationController controller = new LayoutAnimationController(
				set, 0.5f);
		lv.setLayoutAnimation(controller);
	}

	private void checkClearVisibility(boolean eraseButtonInvisible) {
		if (eraseButtonInvisible) {
			eb.setVisibility(View.INVISIBLE);
			RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) b
					.getLayoutParams();
			params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
			b.setLayoutParams(params);
		}
	}

	public void updateEditText() {
		// et.removeTextChangedListener(mTextWatcher);
		// Log.d(TAG, "IndexedDictionaryActivity: updateTextView.");
		String searchString = null;
		if (id.isAutoComplete())
			searchString = id.getAutocompleteSearchString();
		else
			searchString = id.getSearchString();
		et.setCallbackDisabled(true);
		et.setText(searchString);
		et.setCallbackDisabled(false);
		// et.addTextChangedListener(mTextWatcher);
		et.setOnThresholdTextChanged(mThresholdTextChanged);
		et.setThreshold(500);
		et.requestFocus();
	}

	public void updateLanguageButton() {
		IColorSchemeMapper csmi = Prefs.getInstance().getColorSchemeMapper();
		boolean color = Prefs.getInstance().getLanguageButtonColor();
		if (id.getLanguage() == ContentAccess.LANGUAGE_LEFT)
			b.setBackgroundDrawable(csmi.getTitleStyle().getButtons()
					.getDrawable(Buttonizer.GER_DRAWABLE, color));
		else if (id.getLanguage() == ContentAccess.LANGUAGE_RIGHT)
			b.setBackgroundDrawable(csmi.getTitleStyle().getButtons()
					.getDrawable(Buttonizer.UK_DRAWABLE, color));

		b.setOnClickListener(buttonListener);
	}

	public void updateSearchList(boolean setSelectionFromTop) {
		BaseAdapter adapter = null;
		int savedPosition;
		if (id.isAutoComplete()) {
			// Log.d(TAG, "updateSearchList: autocomplete mode.");
			adapter = id.getAutoCompleteAdapter();
			savedPosition = id.getFirstVisibleAutocomplete();
			lv.setOnItemClickListener(mOnAutoCompleteClickListener);

		} else {
			// Log.d(TAG, "updateSearchList: results mode.");
			adapter = id.getIndexedDictionaryAdapter();
			savedPosition = id.getFirstVisibleDictionary();
			lv.setOnItemClickListener(mOnSearchResultClickListener);
		}
		lv.startLayoutAnimation();
		setListAdapter(adapter);
		if (setSelectionFromTop)
			setSelectionFromTop(savedPosition);
	}

	public void saveListPosition() {
		int position = lv.getFirstVisiblePosition();
		if (id.isAutoComplete())
			id.setFirstVisibleAutocomplete(position);
		else
			id.setFirstVisibleDictionary(position);
	}

	private void updateClearButton() {
		eb.setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				if (id.isAutoComplete())
					id.setAutocompleteSearchString("");
				id.setSearchString("");
				id.clear();
				updateEditText();
			}
		});
	}

	public void showErrorDialog(String msg) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(getResources().getString(R.string.error_occurred))
				.setMessage(msg)
				.setCancelable(false)
				.setPositiveButton(getResources().getString(R.string.okay),
						new android.content.DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int which) {
							}
						});
		AlertDialog alert = builder.create();
		alert.show();
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (id == null) {
			return super.onKeyDown(keyCode, event);
		}

		if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && !comesFromHistory) {
			if (!id.isAutoComplete()
					&& id.getAutocompleteSearchString().length() > 0) {
				id.setIsAutoComplete(true);
				// String s = id.getAutocompleteSearchString();
				// id.setSearchString(s);
				updateEditText();
				if (EXECUTE_ANIMATION) {
					applyRotation(DISPLAY_AUTOCOMPLETE_LIST, 180, 90);
				} else {
					updateSearchList(true);
				}

				return true;
			}
		}
		comesFromHistory = false;

		return super.onKeyDown(keyCode, event);
	}

	private void startAutocompleteSearch(String searchString) {
		// Log.d(TAG, "startAutocompleteSearch");
		RESTART_AUTOCOMPLETE = false;
		if (searchString != null)
			id.setAutocompleteSearchString(searchString);
		id.setFirstVisibleAutocomplete(0);

		try {
			id.createAutoCompleteList();
		} catch (Exception e) {
			showErrorDialog(e.getLocalizedMessage());
		}
		lv.startLayoutAnimation();
	}

	private TextWatcher mTextWatcher = new TextWatcher() {

		public void afterTextChanged(Editable arg0) {
			// Log.d(TAG, "TextWatcher: afterTextChanged: '" + arg0.toString()
			// + "'");

			String searchString = new StringBuilder(arg0.toString()).toString();
			if (searchString.equals(id.getAutocompleteSearchString()))
				return;
			if (searchString.equals(id.getSearchString()))
				return;
			startAutocompleteSearch(searchString);
		}

		public void beforeTextChanged(CharSequence s, int start, int count,
				int after) {
		}

		public void onTextChanged(CharSequence s, int start, int before,
				int count) {
		}
	};

	private ThresholdTextChanged mThresholdTextChanged = new ThresholdTextChanged() {

		public void onThresholdTextChanged(Editable text) {
			if (text == null)
				return;
			String searchString = new StringBuilder(text.toString()).toString();
			if (searchString.equals(id.getAutocompleteSearchString()))
				return;
			if (searchString.equals(id.getSearchString()))
				return;
			startAutocompleteSearch(searchString);
		}
	};

	private OnItemClickListener mOnAutoCompleteClickListener = new OnItemClickListener() {

		public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
				long arg3) {
			// Log.d(TAG, "OnAutoCompleteListener: clicked:" + arg2);
			AutoCompleteRecord acr = (AutoCompleteRecord) arg0
					.getItemAtPosition(arg2);
			if (acr.type == AutoCompleteRecord.TYPE_HEADLINE)
				return;

			// Log.d(TAG,
			// "onIitemClick: Release key is = "
			// + ia.indexRecord.getKey());
			saveListPosition();
			id.setIsAutoComplete(false);
			id.setSearchString(acr.getKey());
			updateEditText();
			id.createIndexList(acr.getIndexAll());
			if (EXECUTE_ANIMATION) {
				applyRotation(DISPLAY_RESULT_LIST, 0, 90);
			} else {
				updateSearchList(true);
			}
		}
	};

	private OnItemClickListener mOnSearchResultClickListener = new OnItemClickListener() {
		public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
				long arg3) {
			ViewRecord vr = (ViewRecord) arg0.getItemAtPosition(arg2);

			if (vr.contentType == ViewRecord.CONTENT_KEY) {
				mTitleSelectOnClickListener.setSearchString(vr.content);
				showDialog(DIALOG_TITLE_SELECT);
			} else {
				/*
				 * Intent i = new Intent(getApplicationContext(),
				 * OverviewListActivity.class);
				 * i.putExtra(Overview.bundle_package + "." + Overview.TEXT,
				 * vr.content); startActivity(i);
				 */
			}

		}
	};

	public Context getContext() {
		return this;
	}

	public void setSelectionFromTop(int position) {
		lv.setSelection(position);
	}

	private OnClickListener buttonListener = new OnClickListener() {
		public void onClick(View arg0) {
			int language = id.getLanguage();
			int newLanguage;
			if (language == ContentAccess.LANGUAGE_LEFT)
				newLanguage = ContentAccess.LANGUAGE_RIGHT;
			else
				newLanguage = ContentAccess.LANGUAGE_LEFT;

			id.setLanguage(newLanguage);
			try {
				id.createAutoCompleteList();
			} catch (DatabaseAccessException e) {
				showErrorDialog(e.getLocalizedMessage());
			}
			lv.startLayoutAnimation();
			updateEditText();
		}
	};

	private void applyRotation(int position, float start, float end) {
		// Find the center of the container
		final float centerX = lv.getWidth() / 2.0f;
		final float centerY = lv.getHeight() / 2.0f;

		// Create a new 3D rotation with the supplied parameter
		// The animation listener is used to trigger the next animation
		final Rotate3dAnimation rotation = new Rotate3dAnimation(start, end,
				centerX, centerY, 310.0f, true);
		rotation.setDuration(500);
		rotation.setFillAfter(true);
		rotation.setInterpolator(new AccelerateInterpolator());
		rotation.setAnimationListener(new DisplayNextView(position));

		lv.startAnimation(rotation);
	}

	private final class DisplayNextView implements Animation.AnimationListener {
		private final int mPosition;

		private DisplayNextView(int position) {
			mPosition = position;
		}

		public void onAnimationStart(Animation animation) {
		}

		public void onAnimationEnd(Animation animation) {
			lv.post(new SwapViews(mPosition));
		}

		public void onAnimationRepeat(Animation animation) {
		}
	}

	private final class SwapViews implements Runnable {
		private final int mPosition;

		public SwapViews(int position) {
			mPosition = position;
		}

		public void run() {
			final float centerX = lv.getWidth() / 2.0f;
			final float centerY = lv.getHeight() / 2.0f;
			Rotate3dAnimation rotation;

			if (mPosition == DISPLAY_AUTOCOMPLETE_LIST) {
				rotation = new Rotate3dAnimation(-90, 0, centerX, centerY,
						310.0f, false);
			} else {
				rotation = new Rotate3dAnimation(90, 0, centerX, centerY,
						310.0f, false);
			}

			rotation.setDuration(500);
			rotation.setFillAfter(true);
			rotation.setInterpolator(new DecelerateInterpolator());

			updateSearchList(true);
			lv.startAnimation(rotation);

		}
	}

	public Dialog dialogTitleSelect() {
		AlertDialog ad = new AlertDialog.Builder(this)
				.setTitle(R.string.dialog_title_select)
				.setItems(R.array.dialog_title_select_items,
						mTitleSelectOnClickListener)
				.setNeutralButton(R.string.about_dismiss,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int whichButton) {

								/* User clicked Something so do some stuff */
							}
						}).create();
		return ad;
	}

	private MyTitleSelectOnClickListener mTitleSelectOnClickListener = new MyTitleSelectOnClickListener();

	class MyTitleSelectOnClickListener implements
			DialogInterface.OnClickListener {
		String searchString;

		public void setSearchString(String searchString) {
			this.searchString = searchString;
		}

		public void onClick(DialogInterface dialog, int which) {

			switch (which) {

			// Credits
			case 0:
				id.addHistoryEntry(searchString);
				break;
			// Changelog
			case 1:
				saveListPosition();
				int searchLang = id.getLanguage();
				DictionaryCommand dc = new DictionaryCommand(searchString,
						searchLang);
				dc.execute(IndexedDictionaryActivity.this);
				break;
			// Feedback
			default:

			}
		}
	};

	public static final int DATABASE_UPDATE = 10;

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle item selection
		Intent i;
		switch (item.getItemId()) {
		case R.id.menudictionary:
			i = new Intent(getApplicationContext(), DictionaryActivity.class);
			i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP );
			startActivity(i);
			return true;
		case R.id.menuindexeddictionary:
			i = new Intent(getApplicationContext(),
					IndexedDictionaryActivity.class);
			i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP );
			startActivity(i);
			return true;
		case R.id.searchhistory:
			i = new Intent(getApplicationContext(), HistoryActivity.class);
			startActivity(i);
			return true;
		case R.id.menuupdatedatabase:
			i = new Intent(getApplicationContext(),
					UpdateDatabaseListActivity.class);
			startActivityForResult(i, DATABASE_UPDATE);
			return true;
		case R.id.preferences:
			i = new Intent(getApplicationContext(), Preferences.class);
			startActivity(i);
			return true;
		case R.id.about:
			showDialog(AboutDialogs.ABOUT_DIALOG_MAIN);
			return true;
		default:
			return super.onOptionsItemSelected(item);
		}
	}

}
